﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Galaktika.BI.Silverlight.Controls.OLAP.Info;
using Galaktika.BI.Runtime.Services;
using Galaktika.BI.Silverlight.Controls.General.Tree;
using Galaktika.BI.Silverlight.Controls.MeasureChoice.ClientServer;
using System.Threading;
using Galaktika.BI.Silverlight.Controls.General;
using Galaktika.BI.Silverlight.Commands;

namespace Galaktika.BI.Silverlight.Controls.KpiChoice
{
    public partial class KpiChoiceControl : UserControl
    {
        public KpiChoiceControl()
        {
            InitializeComponent();
        }

        public IBindingContext Context { get; set; }

        #region Свойства для настройки на OLAP
        /// <summary>
        /// 
        /// </summary>
        private String m_Connection = String.Empty;
        /// <summary>
        /// 
        /// </summary>
        public String Connection
        {
            get
            {
                return m_Connection;
            }
            set
            {
                m_Connection = value;
            }
        }

        /// <summary>
        /// Имя OLAP куба
        /// </summary>
        String m_CubeName = String.Empty;
        /// <summary>
        /// Имя OLAP куба
        /// </summary>
        public String CubeName
        {
            get
            {
                return this.m_CubeName;
            }
            set
            {
                m_CubeName = value;
            }
        }
        #endregion Свойства для настройки на OLAP

        private KpiInfo m_SelectedInfo = null;
        public KpiInfo SelectedInfo
        {
            get
            {
                return m_SelectedInfo;
            }
        }

        /// <summary>
        /// Событие генерируется после окончания выбора
        /// </summary>
        public event EventHandler ApplySelection;

        /// <summary>
        /// Событие генерируется при нажатии на кнопку Отмена
        /// </summary>
        public event EventHandler CancelSelection;

        /// <summary>
        /// Генерирует событие "Выбор окончен"
        /// </summary>
        private void Raise_ApplySelection()
        {
            EventHandler handler = ApplySelection;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Генерирует событие "Отмена"
        /// </summary>
        private void Raise_CancelSelection()
        {
            EventHandler handler = CancelSelection;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        public void Initialize()
        {
            RefreshTree();
        }

        private void RefreshTree()
        {
            Tree.Items.Clear();
            //m_GroupNodes.Clear();

            // Добавляем узел Measures
            FolderTreeNode kpisNode = new FolderTreeNode();
            kpisNode.Text = "KPIs";
            Tree.Items.Add(kpisNode);
            kpisNode.ExpandedIcon = UriResources.Images.Kpi16;
            kpisNode.CollapsedIcon = UriResources.Images.Kpi16;

            kpisNode.IsExpanded = true;

            IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
            if (taskManager != null)
            {
                InvokeSchema schema = CommandBuilder.CreateGetKPIsSchema((string)this.Context.UserData["_$Id"], m_Connection, m_CubeName);
                kpisNode.IsWaiting = true;
                taskManager.ProcessTaskItem(Localization.AppTask_DownloadingKPIs,
                    new WaitCallback(GetKPIs),
                    new ChoiceControlInvokeSchemaWrapper(schema, kpisNode));
            }
        }

        private void GetKPIs(object state)
        {
            ChoiceControlInvokeSchemaWrapper wrapper = state as ChoiceControlInvokeSchemaWrapper;
            if (wrapper != null)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeCommand), wrapper);
            }
        }

        void InvokeCommand(object state)
        {
            ChoiceControlInvokeSchemaWrapper wrapper = state as ChoiceControlInvokeSchemaWrapper;
            if (wrapper != null)
            {
                InvokeSchema schema = wrapper.Schema;
                using (SyncDataService ds = new SyncDataService())
                {
                    InvokeResultSchema res = ds.InvokeCommand(schema);

                    if (wrapper.Node != null)
                    {
                        this.Dispatcher.BeginInvoke(delegate { StopWaiting(wrapper.Node); });
                    }

                    if (ds.Error != null)
                    {
                        LogException(ds.Error);
                        return;
                    }

                    this.Dispatcher.BeginInvoke(delegate { GetKPIs_InvokeCommandCompleted(res, wrapper.Node); });
                }
            }
        }

        private bool LogException(Exception ex)
        {
            IOutputService log = (IOutputService)Context.Services.GetService(typeof(IOutputService));
            if (log != null)
            {
                log.WriteException(ex);
                return true;
            }
            return false;
        }

        Dictionary<String, CustomTreeNode> m_GroupNodes = new Dictionary<String, CustomTreeNode>();

        void StopWaiting(CustomTreeNode parentNode)
        {
            if (parentNode != null)
            {
                parentNode.IsWaiting = false;
            }
        }

        void GetKPIs_InvokeCommandCompleted(InvokeResultSchema res, CustomTreeNode parentNode)
        {
            List<KpiInfo> kpis = XmlUtility.XmlStr2Obj<List<KpiInfo>>(res.Content);
            if (kpis != null)
            {
                foreach (KpiInfo info in kpis)
                {
                    CustomTreeNode groupNode = null;
                    
                    //String groupName = String.Empty;
                    //Показатели могут быть сгруппированы в группы. Причем папки могут быть вложенными. Например: "Динамика\\Оборачиваемость"
                    if (!String.IsNullOrEmpty(info.DisplayFolder))
                    {
                        // Если папка по такому же полному пути уже создана то все Ок
                        if (m_GroupNodes.ContainsKey(info.DisplayFolder))
                        {
                            groupNode = m_GroupNodes[info.DisplayFolder];
                        }
                        else
                        {
                            CustomTreeNode prevNode = parentNode;
                            // Разбиваем полный путь на составляющие и создаем папку для каждой из них
                            String[] groups = info.DisplayFolder.Split(new String[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
                            if (groups != null)
                            {
                                foreach (String groupName in groups)
                                {
                                    // Создаем узел для группы
                                    if (!String.IsNullOrEmpty(groupName))
                                    {
                                        if (m_GroupNodes.ContainsKey(groupName))
                                        {
                                            prevNode = m_GroupNodes[groupName];
                                        }
                                        else
                                        {
                                            groupNode = new FolderTreeNode();
                                            groupNode.Text = groupName;
                                            m_GroupNodes[groupName] = groupNode;

                                            if (prevNode == null)
                                                Tree.Items.Add(groupNode);
                                            else
                                                prevNode.Items.Add(groupNode);

                                            prevNode = groupNode;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (groupNode == null)
                        groupNode = parentNode;

                    KpiTreeNode node = new KpiTreeNode(info);
                    // KPI будут конечными узлами. Двойной клик на них будет равнозначен выбору
                    node.Expanded += new RoutedEventHandler(node_Expanded);
                    node.Collapsed += new RoutedEventHandler(node_Collapsed);

                    if (groupNode == null)
                        Tree.Items.Add(node);
                    else
                        groupNode.Items.Add(node);

                }
            }
        }

        void node_Collapsed(object sender, RoutedEventArgs e)
        {
            ApplyItemsSelection();
            Raise_ApplySelection();
        }

        void node_Expanded(object sender, RoutedEventArgs e)
        {
            ApplyItemsSelection();
            Raise_ApplySelection();
        }

        private void ApplyItemsSelection()
        {
            KpiTreeNode node = null;
            node = Tree.SelectedItem as KpiTreeNode;

            if (node != null)
            {
                //Запоминаем выбранный элемент
                m_SelectedInfo = node.Info;
            }
        }
    }
}
